package cn.iotnc.camera.ui.display

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.os.Bundle
import android.view.MenuItem
import android.view.SurfaceView
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import cn.iotnc.camera.R
import cn.iotnc.camera.databinding.ActivityDisplayBinding
import cn.iotnc.camera.model.CameraBean
import cn.iotnc.camera.model.IotncThrowable
import cn.iotnc.camera.ui.widget.StateLayout
import cn.iotnc.camera.util.clicks
import cn.iotnc.camera.util.gone
import cn.iotnc.camera.util.visible
import com.hi.dhl.binding.viewbind
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.jetbrains.anko.*
import java.io.File
import java.io.FileOutputStream
import java.text.SimpleDateFormat
import java.util.*

@AndroidEntryPoint
class DisplayActivity : AppCompatActivity(), AnkoLogger {
    private val viewModel by viewModels<DisplayViewModel>()
    private val binding by viewbind<ActivityDisplayBinding>()

    private lateinit var stateLayout: StateLayout
    private val mediaPlayer: IVLCPlayer by lazy {
        VLCPlayer(applicationContext, binding.textureView).apply {
            setListener(
                onLoading = {
                    showLoading()
                },
                onSuccess = {
                    showContent()
                },
                onError = {
                    showError("连接失败: 无法加载该视频")
                }
            )
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val list = intent?.getParcelableArrayListExtra<CameraBean>(KEY_LIST_BEAN) ?: kotlin.run {
            toast("无法获取到相机信息，请重试!")
            finish()
            return
        }
        var position = intent?.getIntExtra(KEY_POSITION, -1) ?: kotlin.run {
            toast("无法获取到相机信息，请重试!")
            finish()
            return
        }
        if (position == -1) {
            toast("无法获取到相机信息，请重试!")
            finish()
            return
        }
        var bean: CameraBean = list[position]

        stateLayout = StateLayout(this)
            .retry { playWithWorkMode(bean) }
            .wrap(binding.containerDisplay)
            .showLoading("加载中...")

        setSupportActionBar(binding.toolBar)
        supportActionBar?.setDisplayHomeAsUpEnabled(true)

        if (list.size == 1) {
            binding.btnBefore.gone()
            binding.btnNext.gone()
        } else {
            binding.btnBefore.visible()
            binding.btnNext.visible()
        }
        binding.btnBefore.clicks().onEach {
            position--
            if (position < 0) {
                position = list.size - 1
            }
            bean = list[position]
            playWithWorkMode(bean)
        }.launchIn(lifecycleScope)

        binding.btnNext.clicks().onEach {
            position++
            if (position >= list.size) {
                position = 0
            }
            bean = list[position]
            playWithWorkMode(bean)
        }.launchIn(lifecycleScope)

        binding.btnCapture.clicks().onEach {
            val bitmap: Bitmap = (if (bean.workMode == CameraBean.WorkMode.JPG)
                (binding.ivDisplay.drawable as BitmapDrawable?)?.bitmap else binding.textureView.bitmap)
                ?: return@onEach
            val dir = File(externalMediaDirs.first(), supportActionBar?.title.toString()).apply {
                if (!isDirectory) mkdirs()
            }
            val photoFile = File(
                dir, SimpleDateFormat(
                    FILENAME_FORMAT,
                    Locale.US
                ).format(System.currentTimeMillis()) + ".jpg"
            )
            photoFile.outputStream().use {
                bitmap.compress(Bitmap.CompressFormat.JPEG, 80, it)
            }
            toast("保存成功: ${photoFile.absolutePath}")
        }.launchIn(lifecycleScope)

        viewModel.pictureData.observe({ lifecycle }) {
            if (it.isFailure) {
                val throwable = it.exceptionOrNull()
                toast("获取预览数据失败：${throwable?.message ?: "未知错误"}")
                if (throwable == null
                    || (throwable is IotncThrowable
                            && throwable.code != IotncThrowable.NETWORK_ERROR
                            && throwable.code != IotncThrowable.SERVER_ERROR)
                ) {
                    getPicture(bean)
                } else {
                    showError(throwable.message ?: "未知错误")
                }
                return@observe
            }
            warn { "display data: ${it.getOrNull()}" }
            showContent()
            it.getOrThrow().use { input ->
                val bitmap = BitmapFactory.decodeStream(input)
                binding.ivDisplay.setImageBitmap(bitmap)
            }
            if (bean.workMode == CameraBean.WorkMode.JPG) {
                getPicture(bean)
            }
        }

        lifecycleScope.launchWhenResumed {
            playWithWorkMode(bean)
        }
    }

    private fun playWithWorkMode(bean: CameraBean) {
        supportActionBar?.title = bean.ip
        if (bean.workMode == CameraBean.WorkMode.JPG) {
            binding.ivDisplay.visible()
            binding.ivDisplay.tag = bean.ip
            binding.textureView.gone()
            binding.textureView.tag = null
            if (isPlaying()) mediaPlayer.stop()
            getPicture(bean)
        } else {
            binding.ivDisplay.gone()
            binding.ivDisplay.tag = null
            binding.textureView.visible()
            binding.textureView.tag = bean.rtspUrl
            playVideo(bean.rtspUrl)
        }
    }

    private fun getPicture(bean: CameraBean) {
        viewModel.getPicture(bean.ip)
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        if (item.itemId == android.R.id.home) {
            onBackPressed()
        }
        return super.onOptionsItemSelected(item)
    }

    private fun playVideo(url: String) {
        mediaPlayer.playVideo(url)
    }

    private fun isPlaying() = mediaPlayer.isPlaying()

    private fun showContent() {
        stateLayout.showContent()
    }

    private fun showLoading() {
        stateLayout.showLoading("加载中...")
    }

    private fun showError(msg: String) {
        stateLayout.showError(msg)
    }

    override fun onResume() {
        super.onResume()
        binding.textureView.tag?.run {
            mediaPlayer.play()
        }
    }

    override fun onPause() {
        super.onPause()
        binding.textureView.tag?.run {
            mediaPlayer.pause()
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        binding.textureView.tag?.run {
            mediaPlayer.release()
            binding.textureView.tag = null
        }
    }

    companion object {
        private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS"
        private const val KEY_BEAN = "camera_bean"
        private const val KEY_LIST_BEAN = "list_camera_bean"
        private const val KEY_POSITION = "list_position"
        private const val RTSP_URL = "rtsp://%s/ch0"

        fun String.toRtspUrl() = String.format(RTSP_URL, this)

        fun startDisplay(context: Context, bean: CameraBean) {
            context.startActivity<DisplayActivity>(KEY_BEAN to bean)
        }

        fun startDisplay(context: Context, list: MutableList<CameraBean>, position: Int) {
            context.startActivity<DisplayActivity>(KEY_LIST_BEAN to list, KEY_POSITION to position)
        }
    }
}